/**
 * 维吉尼亚密码
 */

public class VigenereCipher {

    /**
     * 单个字符加密
     * @param key 密钥
     * @param m 明文
     * @return 密文
     */
     char encrypt(int key, char m){
         char output;
         //保证key是0-25
         key = ((key % 26) + 26) % 26;
         //判断是否是大写字母
         if (Character.isUpperCase(m)) {
             //把大写字母A-Z转为数字0-25
             int m_int = m - 65;
             //执行公式 C = (M + K) MOD 26
             int c_int = (m_int + key) % 26;
             //把数字0-25转为密文字母A-Z,放到output中
             output = (char) (c_int + 65);
            //判断是否小写字母
         } else if (Character.isLowerCase(m)) {
             //把大写字母A-Z转为数字0-25
             int m_int = m - 97;
             //执行公式 C = (M + K) MOD 26
             int c_int = (m_int + key) % 26;
             //把数字0-25转为密文字母A-Z,放到output中
             output = (char) (c_int + 97);
         } else {
            //如果不是字母，则不做加密解密
             output = m;
         }
         //返回密文字符
         return output;
    }

    /**
     * 单个字符解密
     * @param key 密钥
     * @param c 密文
     * @return 明文
     */
    char decrypt(int key, char c){
         return this.encrypt(-key,  c);
    }

    /**
     * 加密函数
     * @param key 密钥
     * @param input 密文
     * @return
     */
    public String encrypt(String key, String input) {
        //存储密文的字符串
        StringBuilder output = new StringBuilder();
        //密钥改大写
        key = key.toUpperCase();
        int i = 0, k = 0;
        //遍历字符
        for (char m : input.toCharArray()) {
            // 把k循环遍历，并且把k的字母A-Z转换为0-25，做密钥
            k = (int)key.toCharArray()[(i++) % key.length()] - 65;
            //单个字符加密，把密文添加到字符串中
            output.append(this.encrypt(k, m));
        }
        //返回字符串
        return output.toString();
    }
    public String decrypt(String key, String input){
        StringBuilder output = new StringBuilder();
        key = key.toUpperCase();
        int i = 0, k = 0;
        for (char c : input.toCharArray()) {
            // 把k循环遍历，并且把k的字母A-Z转换为0-25，做密钥
            k = (int)key.toCharArray()[(i++) % key.length()] - 65;
            output.append(this.decrypt(k, c));
        }
        return output.toString();
    }

    public static void main(String[] args) {
        VigenereCipher vigenereCipher = new VigenereCipher();
        String ct = vigenereCipher.encrypt("key" , "handsome");
        System.out.println(ct);
        String pt = vigenereCipher.decrypt("key", ct);
        System.out.println(pt);
    }

}
